
package common.packet;

import common.State;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

/**
 * The current state of the match in the game server. It may be running or not.
 * If not yet running the only information about the game are the player list
 * and the players starting position. If already running The player list and their
 * starting position, the score and time.
 *
 * @author xissburg
 */
public class GameState implements Packet
{
    private State state;
    private Collection<ClientInfo> clients;
    private int lTeamPoints, rTeamPoints;
    private int time;//match time in milliseconds

    public GameState()
    {
        state = State.WAITING;
        clients = null;
        lTeamPoints = rTeamPoints = time = 0;
    }

    public GameState(DataInputStream in) throws IOException
    {
        this();
        read(in);
    }

    public GameState(GameState gameState)
    {
        state = gameState.getState();
        lTeamPoints = gameState.getlTeamPoints();
        rTeamPoints = gameState.getrTeamPoints();
        time = gameState.getTime();
        clients = new ArrayList<ClientInfo>(gameState.getClients().size());

        for(ClientInfo ci: gameState.getClients())
            clients.add(ci.copy());
    }

    public void read(DataInputStream in) throws IOException
    {
        state = State.valueOf(in.readUTF());
        lTeamPoints = in.readInt();
        rTeamPoints = in.readInt();
        time = in.readInt();
        int numClients = in.readInt();

        if(numClients > 0)
        {
            clients = new ArrayList<ClientInfo>(numClients);

            for(int i=0; i<numClients; ++i)
            {
                Packet.Code c = Packet.Code.valueOf(in.readUTF());

                if(!c.equals(Packet.Code.CLIENT_INFO))
                    throw new IllegalArgumentException("CLIENT_INFO packet code expected.") ;

                ClientInfo ci = new ClientInfo(in);
                clients.add(ci);
            }
        }
    }

    public void write(DataOutputStream out) throws IOException
    {
        out.writeUTF(getCode().name());
        out.writeUTF(state.name());
        out.writeInt(lTeamPoints);
        out.writeInt(rTeamPoints);
        out.writeInt(time);

        if(clients == null)
        {
            out.writeInt(0);
        }
        else
        {
            out.writeInt(clients.size());

            for(ClientInfo ci: clients)
                ci.write(out);
        }
    }

    public Code getCode() {
        return Code.GAME_STATE;
    }

    public GameState copy() {
        return new GameState(this);
    }
    
    public Collection<ClientInfo> getClients() {
        return clients;
    }

    public void setClients(Collection<ClientInfo> clients) {
        this.clients = clients;
    }

    public int getlTeamPoints() {
        return lTeamPoints;
    }

    public void setlTeamPoints(int lTeamPoints) {
        this.lTeamPoints = lTeamPoints;
    }

    public int getrTeamPoints() {
        return rTeamPoints;
    }

    public void setrTeamPoints(int rTeamPoints) {
        this.rTeamPoints = rTeamPoints;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }
}
